
/****************************************************************************
**
** Copyright (C) 2004-2008 VATATA.com . All rights reserved.
**
** This file is the part of the Miniutil Poject of VATATA.com.
** Vatata's miniutil library is lightweight and portable (for linux
** and Windows). The C++ Class Library included Threadpool, Dll danymic loading, 
** General socket application model and tcp server, httpserver/servlet, etc. 
** It is a pratical utility disigned for who don't want learn the Big C++ 
** Developing Platform, such as  Boost or ACE.
**
** This file may be used under the terms of the GNU General Public
** License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file.  Alternatively you may (at
** your option) use any later version of the GNU General Public
** License if such license has been publicly approved by VATATA.com.
** (or its successors, if any) and the Miniutil Project Aministrators. 
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://www.gnu.org/licenses/lgpl.html. If you are unsure which 
** license is appropriate for your use, please review the following 
** information: http://code.google.com/p/miniutil/ or contact 
** http://www.vatata.com.
**
** In addition, as a special exception, VATATA.com, as the sole
** copyright holder for Miniutil Project, grants users of VATATA
** P2P Platform the right to release and package with the related 
** libraries without the source code.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. vatata reserves all rights not expressly
** granted herein.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/



/*
    async_net.h

    for simple non-block socket io
    
    Wang Bo 
*/

#ifndef __MINIUTIL__ASYNCNET__H__
#define __MINIUTIL__ASYNCNET__H__

#include "miniutil/buffer.h"
#include "miniutil/socket.h"



namespace miniutil
{
    namespace asyncnet
    {

		enum
		{
			ASYN_STUS_IDLE = 0,
			ASYN_STUS_CONNING,
			ASYN_STUS_CONNED,
			ASYN_STUS_FAIL,
			ASYN_STUS_FINI
		};

        struct socket_buffer
        {
            miniutil::data::buffer  r_buf;
            miniutil::data::buffer  w_buf;
            miniutil::mutex         buf_mutex;

            int put_to_buffer( char * data, int len = -1 );

            //// todo
        };

        class session
        {
        public:
			session();
            virtual ~session();

            socket_buffer     sock_buf;

			//return 1, selector should lose the control of this object
            virtual int on_connected();
            virtual int on_accepted();
            virtual int on_disconnected();

            virtual int on_exception( const miniutil::socketException & e );
            virtual int on_recv( );
            virtual int on_sendover( int len );

            virtual void close();

			int session_stus;

            // todo
            //virtual void on_timer( int interval_ms );
            //virtual void on_idle ( int timeout_ms );
            //virtual void on_timeout( int timeout_ms );
        };


        class monitor
        {
        public:
			monitor();
			virtual ~monitor();
            bool connect( const char * host, int port, int timeout_ms = 0 );
            void remove( const char * host, int port ) ;


            bool bind( int port, const miniutil::ip4addr & ip = miniutil::ip4addr::INETANY() );
            void remove( int port , const miniutil::ip4addr & ip = miniutil::ip4addr::INETANY() );

            virtual int on_connected_fail( const char * host, int port ) ;
            virtual int on_connected_timeout(const char * host, int port) ;
            virtual int on_connected( miniutil::socket * p_sock ) ;
            virtual int on_accepted( miniutil::socket * p_sock );

			int moni_stus;
        };

        class async_selector
        {
        public:
			virtual ~async_selector(){}
            virtual bool put( const char * host, int port,  SOCKET sock , monitor * con, int timeout_ms )  = 0;
            virtual void remove( const char * host, int port ) = 0;

            virtual bool put( miniutil::serversocket * p_ssock, monitor * p_acceptor ) = 0;
            virtual void remove( int port , const miniutil::ip4addr & ip  ) = 0;

            virtual bool put( session * p_session , miniutil::socket * p_sock) = 0;
            virtual void remove( session * p_session ) = 0;

			virtual int newconnectinfo(const char* host, int port, monitor *con, int timeout_ms) = 0;

            static async_selector * get_selector();
        };

        template<class _SESSION>
        class factory : public monitor
        {
        public:
            inline virtual int on_connected( miniutil::socket * p_sock ) 
            {
                session * p_session = new _SESSION;
                p_session->on_connected();

                async_selector::get_selector()->put( p_session , p_sock );
				return 0;
            }
            inline virtual int on_accepted( miniutil::socket * p_sock )
            {
                session * p_session = new _SESSION;
                p_session->on_accepted();

                async_selector::get_selector()->put( p_session, p_sock );
				return 0;
            }
        };

    }
}


#endif
